﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary
{
    /// <summary>
    /// This class provides to transform a complex linear system of equation into a real linear 
    /// system of equation.
    /// </summary>
    [Serializable]
    public class ComplexToRealLinearSystemTransform
    {
        /// <summary>
        /// The complex linear system of equation.
        /// </summary>
        private ComplexLinearEquationSystem complexEquationSystem;

        /// <summary>
        /// Initializes a new instance of the <see cref="ComplexToRealLinearSystemTransform"/> class.
        /// </summary>
        /// <param name="complexEquationSystem">The complex linear system of equation.</param>
        public ComplexToRealLinearSystemTransform(ComplexLinearEquationSystem complexEquationSystem)
        {
            this.complexEquationSystem = complexEquationSystem;
        }

        /// <summary>
        /// Gets or sets the complex linear system of equation.
        /// </summary>
        /// <value>The complex linear system of equation.</value>
        public ComplexLinearEquationSystem ComplexEquationSystem
        {
            get { return complexEquationSystem; }
            set { complexEquationSystem = value; }
        }

        /// <summary>
        /// Transforms the specified complex linear system of equation into a real linear system 
        /// of equation.
        /// </summary>
        /// <returns>The transfomed real linear system of equation.</returns>
        public LinearEquationSystem TransformToRealEquationSystem()
        {
            GeneralVector resultVector =
                GeneralVector.UnionVectors(this.complexEquationSystem.ResultVector.ExtractRealNumberPartVector(),
                                           this.complexEquationSystem.ResultVector.ExtractImaginaryNumberPartVector());

            Matrix coefficientMatrix = new Matrix(2 * this.complexEquationSystem.CoefficientMatrix.Rows,
                                                  2 * this.complexEquationSystem.CoefficientMatrix.Columns);

            Matrix tempuri1 =
                Matrix.UnionMatricesVertical(this.complexEquationSystem.CoefficientMatrix.ExtractRealNumberPartMatrix(),
                                             this.complexEquationSystem.CoefficientMatrix.
                                                 ExtractImaginaryNumberPartMatrix().
                                                 CreateSignInvertedMatrix());

            Matrix tempuri2 =
                Matrix.UnionMatricesVertical(
                    this.complexEquationSystem.CoefficientMatrix.ExtractImaginaryNumberPartMatrix(),
                    this.complexEquationSystem.CoefficientMatrix.ExtractRealNumberPartMatrix());

            for (int i = 0; i < tempuri1.Rows; i++)
            {
                for (int j = 0; j < tempuri1.Columns; j++)
                {
                    coefficientMatrix.MatrixData[i, j] = tempuri1.MatrixData[i, j];
                }
            }

            int offset = tempuri1.Rows;

            for (int i = 0; i < tempuri2.Rows; i++)
            {
                for (int j = 0; j < tempuri2.Columns; j++)
                {
                    coefficientMatrix.MatrixData[i + offset, j] = tempuri2.MatrixData[i, j];
                }
            }

            return new LinearEquationSystem(coefficientMatrix, resultVector);
        }
    }
}